<!doctype html>
<html lang="es">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1"/>
  <title>Spanish Chatbot — 1:1 Prototype</title>
  <style>
    :root{
      --bg:#f6f8fb; --ink:#111827; --muted:#6b7280; --card:#ffffff; --ring:#e5e7eb; --btn:#111827; --btn-ink:#ffffff;
      --sel:#4f46e5;
    }
    [data-theme="dark"]{
      --bg:#111827; --ink:#f9fafb; --muted:#9ca3af; --card:#1f2937; --ring:#374151; --btn:#f9fafb; --btn-ink:#111827;
    }
    *{box-sizing:border-box}
    html,body{height:100%}
    body{margin:0; background:var(--bg); font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Noto Sans SC", sans-serif; color:var(--ink); line-height:1.5; display:flex; flex-direction:column; align-items:center;}
    .page{width:100%; max-width:1200px; padding:28px 24px 24px;}
    header{display:flex; align-items:center; justify-content:space-between; gap:16px; margin-bottom:12px;}
    h1{margin:0; font-size:40px; font-weight:800; letter-spacing:.2px}
    .sub{margin:6px 0 0; color:var(--muted); font-size:20px; font-weight:600}
    .left{display:flex; flex-direction:column}
    /* right controls */
    .top-controls{display:flex; align-items:center; gap:12px}
    .modes{background:#fff; border:1px solid var(--ring); border-radius:999px; padding:4px 6px; display:flex; gap:6px}
    .chip{font-size:12px; color:#111827; background:#f9fafb; border:1px solid var(--ring); border-radius:999px; padding:3px 8px; cursor:pointer; transition:all .15s ease}
    .chip:hover{background:#e5e7eb; transform:translateY(-1px); box-shadow:0 2px 4px rgba(0,0,0,.1)}
    .chip.active{background:#4f46e5; color:#fff; border-color:#4f46e5}
    .chip.active:hover{background:#4338ca; transform:translateY(-1px); box-shadow:0 4px 8px rgba(79,70,229,.3)}
    .feedback{display:flex; align-items:center; gap:8px; font-size:12px; color:#111827; background:#fff; border:1px solid var(--ring); border-radius:999px; padding:6px 10px; box-shadow:0 2px 4px rgba(0,0,0,0.04)}
    .feedback.on{border-color:#4f46e5; background:#f5f7ff; color:#2933a3; box-shadow:0 2px 8px rgba(79,70,229,.18)}
    /* iPhone-like switch (smaller) */
    .switch{--w:36px; --h:22px; --knob:18px; width:var(--w); height:var(--h); background:#e5e7eb; border-radius:999px; position:relative; cursor:pointer; transition:background-color .2s ease, box-shadow .2s ease}
    .switch input{display:none}
    .switch i{position:absolute; top:2px; left:2px; width:var(--knob); height:var(--knob); background:#fff; border-radius:50%; transition:left .2s ease; box-shadow:0 1px 3px rgba(0,0,0,.2)}
    .switch.on{ background:#4f46e5; box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
    .switch.on i{ left: calc(var(--w) - var(--knob) - 2px) }
    .badge{display:flex; align-items:center; gap:6px; font-size:14px; color:var(--muted); margin:12px 0 12px}
    .dots{width:12px; height:12px; display:inline-block; background:radial-gradient(#c5c9d3 1px, transparent 1px); background-size:4px 4px}

    /* Suggestions row */
    .suggestions{display:flex; gap:24px; margin:6px 0 18px}
    .card-sug{width:320px; height:140px; border-radius:14px; position:relative; overflow:hidden; border:1px solid var(--ring); box-shadow:0 10px 24px rgba(17,24,39,.06); padding:16px; cursor:pointer; transition:all .2s ease}
    .card-sug:hover{transform:translateY(-3px) scale(1.02); box-shadow:0 16px 32px rgba(17,24,39,.15); border-color:var(--sel)}
    .card-sug.selected{outline:2px solid var(--sel); outline-offset:0; box-shadow:0 14px 34px rgba(79,70,229,.22)}
    .card-sug.selected:hover{transform:translateY(-3px) scale(1.02); box-shadow:0 18px 36px rgba(79,70,229,.25)}
    .card-sug .tag{font-size:20px; font-weight:700}
    .card-sug .subtag{font-size:12px; color:#6b7280; margin-top:8px}
    .c-id{background:linear-gradient(180deg,#eef2ff,#eef1ff)}
    .c-os{background:linear-gradient(180deg,#fde7df,#f7efe9)}
    .c-ih{background:linear-gradient(180deg,#dcfcea,#e7fbf6)}
    .c-cp{background:linear-gradient(180deg,#ccf5d9,#e8ffef)}
    .c-ex{background:linear-gradient(180deg,#fff1cf,#fff6df)}
    /* selected badge */
    .status{position:absolute; bottom:10px; left:16px; right:16px; display:none; align-items:center; justify-content:space-between; gap:8px; border:1px solid #d6ddff; background:#f5f7ff; color:#2933a3; border-radius:8px; padding:6px 8px; font-size:12px}
    .card-sug.selected .status{display:flex}
    .check{width:18px; height:18px; border-radius:50%; border:2px solid #4f46e5; display:grid; place-items:center}
    .check i{width:8px; height:8px; background:#4f46e5; border-radius:50%}

    /* Chat panel */
    .panel{margin-top:12px; background:var(--card); border-radius:18px; border:1px solid var(--ring); min-height:520px; display:flex; flex-direction:column; box-shadow:0 8px 24px rgba(17,24,39,.06)}
    .history{flex:1; border-radius:18px 18px 0 0; padding:16px; overflow:auto}
    /* new chat layout: left-right with avatars */
    .message{display:flex; gap:10px; align-items:flex-start; margin:12px 8px}
    .message.user{flex-direction:row-reverse}
    .avatar{width:36px; height:36px; border-radius:50%; display:grid; place-items:center; box-shadow:0 2px 6px rgba(0,0,0,.08); background:transparent; overflow:hidden}
    .avatar svg{width:100%; height:100%; display:block}
    .bubble{background:#fff; border:1px solid var(--ring); border-radius:14px; padding:12px 14px; max-width:80%; box-shadow:0 4px 12px rgba(17,24,39,.06)}
    .bubble.bot{background:#f5f7ff; border-color:#d6ddff; color:#2933a3}
    /* markdown content inside bubbles */
    .bubble h1,.bubble h2,.bubble h3{margin:6px 0 6px; font-weight:800; color:#111827}
    .bubble h1{font-size:18px}
    .bubble h2{font-size:16px}
    .bubble h3{font-size:15px}
    .bubble p{margin:6px 0}
    .bubble strong{font-weight:800; color:#111827}
    .bubble em{font-style:italic}
    .bubble ul,.bubble ol{margin:6px 0 6px 18px}
    .bubble li{margin:3px 0}
    .bubble blockquote{margin:8px 0; padding-left:10px; border-left:3px solid #e5e7eb; color:#6b7280}
    .bubble code{background:#f3f4f6; padding:2px 4px; border-radius:4px; font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
    .composer{border-top:1px solid var(--ring); display:flex; align-items:center; gap:12px; padding:14px; border-radius:0 0 18px 18px}
    .icons{display:flex; gap:10px; align-items:center}
    .icon-btn{width:34px; height:34px; border-radius:10px; border:1px solid var(--ring); background:#fff; display:grid; place-items:center; cursor:pointer; transition:all .15s ease}
    .icon-btn:hover{background:#f9fafb; border-color:#d1d5db; transform:translateY(-1px); box-shadow:0 2px 8px rgba(0,0,0,.1)}
    .icon-btn:active{transform:translateY(0); box-shadow:0 1px 4px rgba(0,0,0,.1)}
    .icon{width:18px; height:18px; display:block}
    .input{flex:1; display:flex; align-items:center; border:1px solid var(--ring); border-radius:999px; background:#fff; overflow:hidden; transition: box-shadow .15s ease, border-color .15s ease}
    .input:focus-within{ border-color:#a5b4fc; box-shadow:0 0 0 3px rgba(79,70,229,.18) }
    .input textarea{border:0; outline:0; resize:none; padding:12px 14px; width:100%; height:42px; max-height:140px; font-size:14px; color:#111827; transition: height .12s ease}
    .send{width:34px; height:34px; border-radius:50%; border:0; background:var(--btn); color:var(--btn-ink); display:grid; place-items:center; cursor:pointer; margin-left:8px; transition: all .15s ease}
    .send.ready{ transform: translateY(-1px); opacity: 1 }
    .send.ready:hover{ transform: translateY(-2px) scale(1.05); box-shadow: 0 4px 12px rgba(0,0,0,.2); background: #000 }
    .send.ready:active{ transform: translateY(0) scale(1); box-shadow: 0 2px 6px rgba(0,0,0,.15) }
    .send:not(.ready){ opacity:.6 }
    .send:not(.ready):hover{ transform: translateY(-1px); opacity: .8 }
    
    /* error toast */
    .toast{position:fixed; top:20px; right:20px; background:#ef4444; color:#fff; padding:12px 16px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,.15); z-index:1000; transform:translateX(100%); transition:transform .3s ease; max-width:300px}
    .toast.show{transform:translateX(0)}
    .visually-kept{position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden}
    @media (max-width:1280px){.page{max-width:1100px}.card-sug{width:260px}}
    @media (max-width:900px){.suggestions{gap:12px}.card-sug{width:48%; height:130px}}
  .helper{display:none !important}
  </style>
</head>
<body data-theme="light">
  <div class="page">
    <header>
      <div class="left">
        <h1>ME LLAMO LLAMA</h1>
        <p class="sub">¿Vamos a practicar el español?</p>
      </div>
      <div class="top-controls">
        <div class="modes">
          <span class="chip" data-mode="system">Sistema</span>
          <span class="chip" data-mode="dark">Oscuro</span>
          <span class="chip active" data-mode="light">Claro</span>
        </div>
        <label class="feedback"><span id="fb-text">Feedback en español</span><span class="switch" aria-hidden="true"><input id="fb-es" type="checkbox" checked><i></i></span></label>
      </div>
    </header>
    <div class="badge"><span class="dots"></span><span>Temas sugeridos</span></div>
    <div class="suggestions" aria-label="Temas sugeridos">
      <div class="card-sug c-id" data-key="c-id">
        <div class="tag">Identidades</div>
        <div class="subtag">Relata quién eres y tus raíces culturales.</div>
        <div class="status"><span>Modo de tema actual</span><span class="check"><i></i></span></div>
      </div>
      <div class="card-sug c-os" data-key="c-os">
        <div class="tag">Organización Social</div>
        <div class="subtag">Comunidades, normas y gobiernos.</div>
      </div>
      <div class="card-sug c-ih" data-key="c-ih">
        <div class="tag">Ingenio Humano</div>
        <div class="subtag">Habla de ciencia, tecnología e innovación.</div>
      </div>
      <div class="card-sug c-cp" data-key="c-cp">
        <div class="tag">Compartir el Planeta</div>
        <div class="subtag">Medio ambiente, recursos y sostenibilidad.</div>
      </div>
      <div class="card-sug c-ex" data-key="c-ex">
        <div class="tag">Experiencias</div>
        <div class="subtag">Cuenta vivencias pasadas o aprendizajes clave.</div>
      </div>
    </div>

    <section class="panel">
      <div class="history"></div>
      <div class="composer">
        <button class="icon-btn" id="attach-btn" title="Adjuntar archivos" aria-label="Adjuntar archivos"><svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-8.49 8.49a6 6 0 1 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66L9.64 17.9a2 2 0 1 1-2.83-2.83l8.49-8.49"/></svg></button>
        <input type="file" id="file-input" class="visually-kept" multiple accept=".txt,.md,.log,.csv,.json,.html,.htm,.pdf,.docx,.jpg,.jpeg,.png,.bmp,.tiff,.webp">
        <button class="icon-btn" id="mic-btn" title="Grabar audio" aria-label="Grabar audio"><svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 14a4 4 0 0 0 4-4V7a4 4 0 0 0-8 0v3a4 4 0 0 0 4 4z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg></button>
        <div class="input"><textarea placeholder="Escribe en español..." id="chat-input"></textarea></div>
        <button class="send" aria-label="Enviar" id="send-btn"><svg class="icon" viewBox="0 0 24 24" fill="currentColor"><path d="M2 21l21-9L2 3v7l15 2-15 2v7z"/></svg></button>
        <button class="icon-btn" id="export-log-btn" title="Exportar historial" aria-label="Exportar historial"><svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg></button>
        <button class="icon-btn" id="export-btn" title="Exportar PDF" aria-label="Exportar PDF"><svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></button>
      </div>
    </section>
  </div>

  <!-- libs for screenshot to PDF -->
  <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js"></script>

  <script>
    // Default language Spanish
    document.documentElement.lang = 'es';
    if (window.marked) { try { window.marked.setOptions({ breaks: true, gfm: true }); } catch(_){} }

    // Theme switching
    const chips = document.querySelectorAll('.chip');
    chips.forEach(chip => {
      chip.addEventListener('click', () => {
        chips.forEach(c => c.classList.remove('active'));
        chip.classList.add('active');
        const mode = chip.getAttribute('data-mode');
        if(mode === 'dark'){
          document.body.setAttribute('data-theme','dark');
        } else {
          document.body.setAttribute('data-theme','light');
        }
      });
    });

    // Feedback language switch (Spanish on/off)
    const FB_STORAGE_KEY = 'fb_es_on';
    const fbInput = document.getElementById('fb-es');
    const fbLabel = document.querySelector('label.feedback');
    const fbSwitchEl = fbLabel ? fbLabel.querySelector('.switch') : null;
    function applyFeedbackUI(){
      const on = !!(fbInput && fbInput.checked);
      if(fbLabel){ fbLabel.classList.toggle('on', on); }
      if(fbSwitchEl){ fbSwitchEl.classList.toggle('on', on); }
      
      // Update text based on switch state
      const fbText = document.getElementById('fb-text');
      if(fbText){
        fbText.textContent = on ? 'Feedback in English' : 'Feedback en español';
      }
      
      try{ localStorage.setItem(FB_STORAGE_KEY, on ? '1' : '0'); }catch(_){/* ignore */}
    }
    // init from storage
    try{
      const saved = localStorage.getItem(FB_STORAGE_KEY);
      if(saved === '0' && fbInput){ fbInput.checked = false; }
      if(saved === '1' && fbInput){ fbInput.checked = true; }
    }catch(_){/* ignore */}
    applyFeedbackUI();
    if(fbInput){ fbInput.addEventListener('change', applyFeedbackUI); }

    // Card select + persist
    const STORAGE_KEY = 'selected-card-key';
    const cards = Array.from(document.querySelectorAll('.card-sug'));
    function applySelection(key){
      cards.forEach(c => c.classList.toggle('selected', c.getAttribute('data-key') === key));
    }
    // flat avatar SVGs
    function faceSVG({skin='#FFE7C6', eye='#262626', mouth='#D97706', bg='#EEF2FF', accent='#4F46E5'}){
      return `\n<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">\n  <defs>\n    <clipPath id="clipR"><circle cx="32" cy="32" r="32"/></clipPath>\n  </defs>\n  <g clip-path="url(#clipR)">\n    <rect x="0" y="0" width="64" height="64" fill="${bg}"/>\n    <!-- head -->\n    <circle cx="32" cy="36" r="20" fill="${skin}"/>
    <!-- hair/cap filling to edges for full look -->\n    <path d="M0 24C12 10 52 10 64 24v10H0z" fill="${accent}"/>\n    <!-- eyes -->\n    <circle cx="24" cy="36" r="2.2" fill="${eye}"/>\n    <circle cx="40" cy="36" r="2.2" fill="${eye}"/>\n    <!-- mouth -->\n    <path d="M26 45c4 3 8 3 12 0" stroke="${mouth}" stroke-width="2.5" stroke-linecap="round" fill="none"/>\n  </g>\n</svg>`;
    }
    function getTeacherAvatarSVG(key){
      switch(key){
        case 'c-id': return faceSVG({accent:'#8B5CF6', bg:'#F5F3FF'}); // purple
        case 'c-os': return faceSVG({accent:'#06B6D4', bg:'#ECFEFF'}); // cyan
        case 'c-ih': return faceSVG({accent:'#2563EB', bg:'#EFF6FF'}); // blue
        case 'c-cp': return faceSVG({accent:'#16A34A', bg:'#ECFDF5'}); // green
        case 'c-ex': return faceSVG({accent:'#F59E0B', bg:'#FFFBEB'}); // amber
        default: return faceSVG({accent:'#4F46E5', bg:'#EEF2FF'});
      }
    }
    function getStudentAvatarSVG(){
      return faceSVG({accent:'#111827', bg:'#F3F4F6'});
    }
    function createMessage(role, text, teacherKey){
      const h = document.querySelector('.history');
      const row = document.createElement('div');
      row.className = 'message ' + (role === 'bot' ? 'bot' : 'user');
      const avatar = document.createElement('div');
      avatar.className = 'avatar';
      avatar.innerHTML = role === 'bot' ? getTeacherAvatarSVG(teacherKey) : getStudentAvatarSVG();
      const bubble = document.createElement('div');
      bubble.className = 'bubble ' + (role === 'bot' ? 'bot' : 'user');
      if(role === 'bot' && window.marked && window.DOMPurify){
        const html = window.marked.parse(String(text || ''));
        bubble.innerHTML = window.DOMPurify.sanitize(html);
      }else{
        bubble.textContent = text;
      }
      row.appendChild(avatar);
      row.appendChild(bubble);
      h.appendChild(row);
      h.scrollTop = h.scrollHeight;
      return bubble;
    }
    function appendBotMessage(text){
      return createMessage('bot', text, window.__currentTopicKey || localStorage.getItem('selected-card-key') || '');
    }
    async function askLLM(tagKey){
      try{
        const res = await fetch('/api/ask', {
          method:'POST',
          headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ tag: tagKey })
        });
        if(!res.ok){
          const msg = await res.text();
          throw new Error(msg || 'Request failed');
        }
        const data = await res.json();
        return data.question || '';
      }catch(err){
        console.error(err);
        const msg = (err && err.message) ? String(err.message) : '';
        return `No se pudo obtener la pregunta: ${msg || 'Error desconocido. Revisa backend y la API Key.'}`;
      }
    }
    async function chatLLM(history){
      try{
        const res = await fetch('/api/chat', {
          method:'POST',
          headers:{'Content-Type':'application/json'},
          body: JSON.stringify({
            messages: history,
            attachments: attachments,
            topicKey: (window.__currentTopicKey || localStorage.getItem('selected-card-key') || ''),
            temperature: 0.7,
            max_tokens: 512
          })
        });
        if(!res.ok){
          const msg = await res.text();
          throw new Error(msg || 'Request failed');
        }
        const data = await res.json();
        return data.reply || '';
      }catch(err){
        console.error(err);
        const msg = (err && err.message) ? String(err.message) : '';
        return `No se pudo obtener la respuesta: ${msg || 'Error desconocido.'}`;
      }
    }
    // restore
    let currentKey = localStorage.getItem(STORAGE_KEY);
    const savedKey = currentKey;
    if(savedKey){
      applySelection(savedKey);
      window.__currentTopicKey = savedKey;
    } else {
      // default select the first card
      const firstKey = cards[0]?.getAttribute('data-key');
      if(firstKey){
        applySelection(firstKey);
        localStorage.setItem(STORAGE_KEY, firstKey);
        window.__currentTopicKey = firstKey;
      }
    }
    // events
    cards.forEach(card => {
      card.addEventListener('click', () => {
        const key = card.getAttribute('data-key');
        applySelection(key);
        localStorage.setItem(STORAGE_KEY, key);
        window.__currentTopicKey = key;
        const placeholder = appendBotMessage('Generando pregunta...');
        askLLM(key).then(q => {
          placeholder.textContent = q || 'No se recibió ninguna pregunta.';
        });
      });
    });

    // chat
    const inputEl = document.getElementById('chat-input');
    const sendBtn = document.getElementById('send-btn');
    const historyEl = document.querySelector('.history');
    const chatMessages = [];
    const attachments = [];

    function appendUser(text){
      return createMessage('user', text);
    }
    function appendBot(text){
      return createMessage('bot', text, window.__currentTopicKey || '');
    }
    function appendSubNote(parentEl, text){
      const sub = document.createElement('div');
      sub.style.fontSize = '12px';
      sub.style.color = '#6b7280';
      sub.style.marginTop = '6px';
      sub.textContent = text;
      parentEl.appendChild(sub);
    }
    function showToast(message, duration = 3000){
      const toast = document.createElement('div');
      toast.className = 'toast';
      toast.textContent = message;
      document.body.appendChild(toast);
      setTimeout(() => toast.classList.add('show'), 10);
      setTimeout(() => {
        toast.classList.remove('show');
        setTimeout(() => toast.remove(), 300);
      }, duration);
    }

    function renderMarkdownInto(el, text){
      if(window.marked && window.DOMPurify){
        const html = window.marked.parse(String(text || ''));
        el.innerHTML = window.DOMPurify.sanitize(html);
      } else {
        el.textContent = text || '';
      }
    }
    
    function validateInput(text){
      if(!text || !text.trim()) return false;
      const trimmed = text.trim();
      if(/^\d+$/.test(trimmed)) return false; // pure numbers
      
      // Check for Chinese characters
      if(/[\u4e00-\u9fff]/.test(trimmed)){
        return {valid: false, reason: 'chinese'};
      }
      
      return {valid: true};
    }
    
    function sendCurrent(){
      const text = (inputEl.value || '').trim();
      const validation = validateInput(text);
      if(!validation.valid){
        if(validation.reason === 'chinese'){
          showToast('Please enter text in Spanish, not Chinese.');
        } else {
          showToast('Please enter valid text content.');
        }
        return;
      }
      inputEl.value = '';
      autoResize();
      appendUser(text);
      const placeholder = appendBot('Pensando...');
      const hist = [
        { role:'system', content:'Eres un docente de español. Da respuestas claras y breves en español.' },
        ...chatMessages,
        { role:'user', content:text }
      ];
      // include attachment names in last user turn
      if(attachments.length){
        hist.push({ role:'user', content:`Adjuntos: ${attachments.map(a=>a.name).join(', ')}`});
      }
      chatLLM(hist).then(async r => {
        renderMarkdownInto(placeholder, r || 'Sin respuesta.');
        chatMessages.push({ role:'user', content:text });
        chatMessages.push({ role:'assistant', content:r });
        // When switch is ON, append an English hint below the response
        const fbSwitch = document.getElementById('fb-es');
        const englishHintEnabled = fbSwitch && fbSwitch.checked;
        if(englishHintEnabled && r){
          try{
            const tr = await fetch('/api/translate', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ text: r, target: 'en' }) });
            if(tr.ok){
              const data = await tr.json();
              const hint = String(data.translated || '').trim();
              if(hint){ appendSubNote(placeholder, hint); }
            }
          }catch(e){ /* ignore hint errors */ }
        }
      });
    }
    sendBtn.addEventListener('click', sendCurrent);
    inputEl.addEventListener('keydown', (e) => {
      if(e.key === 'Enter' && !e.shiftKey){ e.preventDefault(); sendCurrent(); }
    });

    // textarea auto-resize & send button state
    function autoResize(){
      inputEl.style.height = '42px';
      const next = Math.min(inputEl.scrollHeight, 140);
      inputEl.style.height = next + 'px';
      const hasText = !!(inputEl.value && inputEl.value.trim());
      sendBtn.classList.toggle('ready', hasText);
    }
    inputEl.addEventListener('input', autoResize);
    autoResize();

    // attachments
    const fileInput = document.getElementById('file-input');
    const attachBtn = document.getElementById('attach-btn');
    attachBtn.addEventListener('click', ()=> fileInput.click());
    fileInput.addEventListener('change', async () => {
      if(!fileInput.files || !fileInput.files.length) return;
      for(const file of fileInput.files){
        const fd = new FormData();
        fd.append('file', file);
        try{
          const res = await fetch('/api/upload', { method:'POST', body: fd });
          if(!res.ok){ throw new Error(await res.text()); }
          const data = await res.json();
          attachments.push({ name: data.filename, url: data.url });
          
          // Check if it's an image and show preview
          const isImage = /\.(jpg|jpeg|png|bmp|tiff|webp)$/i.test(file.name);
          if(isImage){
            const statusMsg = appendBot(`Imagen subida: ${data.filename} (OCR en progreso...)`);
            // Update status after a short delay to show completion
            setTimeout(() => {
              statusMsg.textContent = `Imagen procesada: ${data.filename} (OCR completado)`;
            }, 2000);
          } else {
            appendBot(`Archivo subido: ${data.filename}`);
          }
        }catch(err){
          console.error(err);
          appendBot('Fallo al subir archivo');
        }
      }
      fileInput.value = '';
    });

    // voice input via Web Speech API (Chrome/Edge)
    const micBtn = document.getElementById('mic-btn');
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    let rec = null;
    if(SR){
      rec = new SR();
      rec.lang = 'auto';
      rec.interimResults = false;
      rec.maxAlternatives = 1;
      rec.onresult = async (ev) => {
        const transcript = ev.results[0][0].transcript || '';
        if(!transcript) return;
        // translate to Spanish before sending
        try{
          const tr = await fetch('/api/translate', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ text: transcript }) });
          if(!tr.ok){ throw new Error(await tr.text()); }
          const data = await tr.json();
          inputEl.value = (data.spanish || '').trim();
          sendCurrent();
        }catch(err){
          console.error(err);
          appendBot('No se pudo traducir el audio.');
        }
      };
      rec.onerror = (e)=>{ console.error(e); appendBot('Fallo de reconocimiento de voz.'); };
      micBtn.addEventListener('click', ()=>{ try{ rec.start(); }catch(_){} });
    } else {
      micBtn.addEventListener('click', ()=> appendBot('El navegador no soporta reconocimiento de voz.'));
    }

    // export chat as PDF (text-based bubbles, selectable; fallback to screenshot)
    const exportBtn = document.getElementById('export-btn');
    const exportLogBtn = document.getElementById('export-log-btn');
    async function exportChatAsPDF(){
      try{
        const panel = document.querySelector('.panel');
        const history = panel.querySelector('.history');
        const { jsPDF } = window.jspdf || {};

        if(jsPDF){
          const pdf = new jsPDF('p', 'mm', 'a4');
          const margin = 12;
          const pageW = pdf.internal.pageSize.getWidth();
          const pageH = pdf.internal.pageSize.getHeight();
          const bubbleMaxW = pageW - margin*2 - 20; // some side space
          const lineH = 6.5;
          let y = margin;

          pdf.setFont('helvetica', 'normal');
          pdf.setFontSize(11);

          const nodes = history.querySelectorAll('.message');
          nodes.forEach((row) => {
            const isUser = row.classList.contains('user');
            const bubble = row.querySelector('.bubble');
            if(!bubble) return;
            const text = (bubble.textContent || '').replace(/\s+$/,'');

            const lines = pdf.splitTextToSize(text, bubbleMaxW - 14); // padding inside
            const bh = lines.length * lineH + 10; // padding top/bottom 5mm each

            // page break if needed
            if(y + bh > pageH - margin){
              pdf.addPage();
              y = margin;
            }

            // bubble x based on side
            const bw = Math.min(bubbleMaxW, Math.max(40, pdf.getTextWidth(lines.join(' ')) + 14));
            const x = isUser ? (pageW - margin - bw) : margin;

            // draw rounded rect bubble
            const r = 3;
            if(isUser){ pdf.setDrawColor(180); pdf.setFillColor(255,255,255); }
            else { pdf.setDrawColor(210, 220, 255); pdf.setFillColor(245, 247, 255); }
            pdf.roundedRect(x, y, bw, bh, r, r, 'FD');

            // text color per role
            if(isUser){ pdf.setTextColor(17,24,39); } else { pdf.setTextColor(41,51,163); }

            // write lines
            let ty = y + 6; // top padding
            lines.forEach(ln => {
              pdf.text(ln, x + 7, ty);
              ty += lineH;
            });

            y += bh + 4; // gap between bubbles
          });

          const ts = new Date().toISOString().replace(/[:.]/g, '-');
          pdf.save(`chat-export-${ts}.pdf`);
          return;
        }

        // fallback: 图片式导出
        if(typeof html2canvas !== 'undefined'){
          const prev = { height: history.style.height, overflow: history.style.overflow };
          history.style.height = history.scrollHeight + 'px';
          history.style.overflow = 'visible';
          const canvas = await html2canvas(panel, { scale: 2, backgroundColor: '#ffffff' });
          history.style.height = prev.height; history.style.overflow = prev.overflow;
          const imgData = canvas.toDataURL('image/png');
          const pdf = new (window.jspdf && window.jspdf.jsPDF ? window.jspdf.jsPDF : jsPDF)('p','mm','a4');
          const pageWidth = pdf.internal.pageSize.getWidth();
          const pageHeight = pdf.internal.pageSize.getHeight();
          const imgWidth = pageWidth;
          const imgHeight = canvas.height * imgWidth / canvas.width;
          let position = 0;
          pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
          while((imgHeight - position) > pageHeight){
            position -= pageHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
          }
          const ts = new Date().toISOString().replace(/[:.]/g, '-');
          pdf.save(`chat-export-${ts}.pdf`);
          return;
        }

        // 最后兜底：使用浏览器打印
        window.print();
      }catch(err){
        console.error(err);
        appendBot('Fallo al exportar PDF.');
      }
    }
    exportBtn.addEventListener('click', exportChatAsPDF);
    exportLogBtn.addEventListener('click', async () => {
      try{
        const res = await fetch('/api/export_pdf');
        if(!res.ok){
          const t = await res.text();
          appendBot(`No se pudo exportar el historial: ${t || res.status}`);
          return;
        }
        const blob = await res.blob();
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url; a.download = `chat-export-${new Date().toISOString().replace(/[:.]/g,'-')}.pdf`;
        document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url);
      }catch(err){
        console.error(err); appendBot('No se pudo exportar el historial.');
      }
    });

    // Warn user before leaving if chat has content
    window.addEventListener('beforeunload', (e) => {
      const hasMessages = document.querySelectorAll('.message').length > 0;
      if(hasMessages){
        e.preventDefault();
        e.returnValue = 'Chat history has not been exported. Are you sure you want to leave?';
        return e.returnValue;
      }
    });
  </script>
</body>
</html>
